#!/usr/bin/env python

from kivy.logger import Logger

from kivy.metrics import dp
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.uix.scrollview import ScrollView
from kivy.uix.textinput import TextInput

from amgineirc.view.messageView import MessageView
from amgineirc.viewModel.settings.rulesViewModel import RulesViewModel

__all__ = ['EditRulePopup', 'RulesView']

class EditRulePopup(Popup, MessageView):
    
    def __init__(self, command, name, validate_handler):
        self.key = name
        self.command = command
        self.validate_handler = validate_handler
        layout = FloatLayout()
        Popup.__init__(self,
                       title=command + ' ' + name,
                       content=layout,
                       size_hint=(None, None),
                       size=(400, 200),
                       auto_dismiss=False)
        MessageView.__init__(self)
        # rotary encryption rule name
        label = self.buildFormLabel('Rotary Encryption Rule Name',
                                    'Only letters and digits and "_" underscore.',
                                     size_hint=(0.5, 0.5),
                                     pos_hint={'x':0.0, 'y':0.5})
        self.name_input = TextInput(text=name,
                                    multiline=False,
                                    size_hint=(0.5, 0.5),
                                    pos_hint={'x':0.5, 'y':0.5})
        layout.add_widget(label)
        layout.add_widget(self.name_input)
        # command button
        layout.add_widget(Button(text=RulesView.submit_command,
                                 size_hint=(0.5, 0.25),
                                 pos_hint={'x':0.0, 'y':0.0},
                                 on_press=self.validate_data))
        layout.add_widget(Button(text='Cancel',
                                 size_hint=(0.5, 0.25),
                                 pos_hint={'x':0.5, 'y':0.0},
                                 on_press=self.dismiss))


    def validate_data(self, instance):
        ok, msg = self.validate_handler(instance.text,
                                        self.key,
                                        self.name_input.text.strip())
        if ok:
            self.dismiss()
        else:
            self.message_warn(msg)
                
        
class _RuleRecordButton(Button, MessageView):
    def __init__(self, name, vm_command_option_handler, **kargs):
        if 'text' in kargs:
            del(kargs['text'])
        kargs['markup'] = True   
        kargs['on_press'] = self.w_handle_rule_record_button_on_press
        kargs['size_hint'] = (1.0, None)
        kargs['height'] = dp(50)
        Button.__init__(self, **kargs)
        MessageView.__init__(self)
        self.reset_text(name)
        self.name = name
        self.vm_command_option_handler = vm_command_option_handler
        
    def reset_text(self, name):
        self.name = name
        self.text = '[b]' + name + '[/b]'
        
    def w_handle_rule_record_button_on_press(self, instance):
        self.select_options('Options for ' + self.name,
                            RulesView.commands,
                            self.vm_command_option_handler,
                            self.name)
            

class _RulesListView(ScrollView):
    def __init__(self, command_option_handler, **kargs):
        kargs['do_scroll_x'] = False
        ScrollView.__init__(self, **kargs)
        # view model command handling method
        self.command_option_handler = command_option_handler
        # create a default grid layout with custom width/height
        self._layout = GridLayout(cols=1,
                                  size_hint=(1.0, None))
        # when we add children to the grid layout, its size doesn't change at
        # all. we need to ensure that the height will be the minimum required to
        # contain all the childs. (otherwise, we'll child outside the bounding
        # box of the childs)
        self._layout.bind(minimum_height=self._layout.setter('height'))
        self.add_widget(self._layout)
        
    def log(self, name):
        w = _RuleRecordButton(name, self.command_option_handler)
        y = self.scroll_y
        self._layout.add_widget(w)
        # if the scroll view was scrolled to the end
        # then stay at the end
        if y == 1.0:
            self.scroll_y = y
        return w


class RulesView(FloatLayout, MessageView):
    """a view for the domains page
        
        use bind_apply to bind the vm method to read and store the vars
        use bind_reset to bind the vm method to reset the vars

    """
    submit_command = 'Submit'
    create_command = 'Create A New Rotary Encryption Rule'
    import_command = 'Import A New Rotary Encryption Rule'
    delete_command = 'Delete'
    edit_command = 'Rename'
    export_command = 'Export'
    
    commands = [edit_command, delete_command, export_command]
    
    page_intro = "This page is where you can create, import, edit, delete and export your rotary encryption rules."\
                 " You can edit, delete or export a rotary encryption rule by clicking on its name in the list."
                 #" Your rotary encryption rules are currently stored at '{0}'."\
                 #" Each rotary encryption rule file is named with your rotary encryption rule name and with the extension '{1}'."\
                 #" example: 'freedom{1}'."

    def __init__(self, appdata, **kargs):
        FloatLayout.__init__(self, **kargs)
        MessageView.__init__(self)
        self._appdata = appdata
        # page heading
        text = self.__class__.page_intro.format(appdata['rules'].get_path(), appdata['rules'].fn_ext)
        self.intro = Label(text=text,
                           size_hint=(1.0, 0.4),
                           pos_hint={'x':0.0, 'y':0.6},
                           line_height=1.5)
        self.bind(width=self.on_width_handler)
        self.add_widget(self.intro)
        self.create_button = Button(text=self.__class__.create_command,
                                 size_hint=(0.5, 0.2),
                                 pos_hint={'x':0.0, 'y':0.4})
        self.create_button.bind(on_press=self.w_add_button_handler)
        self.add_widget(self.create_button)
        self.import_button = Button(text=self.__class__.import_command,
                                 size_hint=(0.5, 0.2),
                                 pos_hint={'x':0.5, 'y':0.4})
        self.import_button.bind(on_press=self.w_add_button_handler)
        self.add_widget(self.import_button)
        # list of current domains
        self.list_view = _RulesListView(self.w_command_option_handler,
                                        size_hint=(1.0, 0.4),
                                        pos_hint={'x':0.0, 'y':0.0})
        self.add_widget(self.list_view)
        self._rules = {}
        self.vm_option_command_handler = lambda **kargs : None
        # initialize the view model
        RulesViewModel(self, appdata)

    def on_width_handler(self, instance, value):
        if value > 40:
            value -= 20
        self.intro.text_size = (value-20, None)
 
    # widget methods
            
    def w_command_option_handler(self, command, name):
        # the user has selected a command for a rule record
        # instance is a _RuleOptionButton
        if self.vm_option_command_handler is not None:
            self.vm_option_command_handler(command, name)
            
    def w_add_button_handler(self, instance):
        if self.vm_option_command_handler is not None:
            self.vm_option_command_handler(instance.text, '')
        
    # vm methods

    def vm_add_rule(self, name):
        if name not in self._rules:
            self._rules[name] = self.list_view.log(name)

    def vm_show_rule_added(self, name):
        self.vm_add_rule(name)
        # inform user of the added rule
        self.message_success('Added "%s"' % (name))
        
    def vm_show_rule_edited(self, oldname, newname):
        if oldname in self._rules:
            self._rules[newname] = self._rules[oldname]
            self._rules[newname].reset_text(newname)
            del(self._rules[oldname])
            # inform user of the rename
            self.message_success('Modified "%s"' % (newname))

    def vm_show_rule_deleted(self, name):
        if name in self._rules:
            self._rules[name].parent.remove_widget(self._rules[name])
            # self.list_view.remove_widget(self._rules[name])
            del(self._rules[name])
            # inform user of the deleted rule
            self.message_success('Deleted "%s"' % (name))
        
    def vm_bind_command(self, func):
        # func must accept **kargs
        # 'command', 'domain_name', 'new_name'
        self.vm_option_command_handler = func
